<?php

namespace app\ws\controller\gatewayworker;

use app\api\business\LabelBus as LabelBus;
use app\common\model\redis\RedisModel;
use app\common\lib\CurlHandle;
use app\ws\controller\GatewayService;
use GatewayWorker\Lib\Gateway;
use think\facade\Db;
use think\worker\Application;
use Workerman\Worker;
use think\facade\Log;
use Workerman\Lib\Timer;
use app\api\controller\Service;
class Events
{

    /**
     * onWorkerStart 事件回调
     * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
     *
     * @access public
     * @param  \Workerman\Worker    $businessWorker
     * @return void
     */
    public static function onWorkerStart(Worker $businessWorker)
    {
        $app = new Application;
        $app->initialize();
        Log::write("启动Worker");
        //exec('chmod -R 0777 /opt/huisheng/wwwroot/api.raisound.com/html/dialogue_robot/public/label_meta.txt');
        //exec('chmod -R 0777 /opt/huisheng/wwwroot/api.raisound.com/html/dialogue_robot/public/train_meta.txt');
        // 定时器
        Events::timer();
        Events::synchronizationInstruction();
    }

    /**
     * onConnect 事件回调
     * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
     *
     * @access public
     * @param  int       $client_id
     * @return void
     */
    public static function onConnect($client_id)
    {
//        $Service = new GatewayService();
//        $Service->wsReturnResult($client_id,[],'连接成功！',$Service->make['events']);
    }

    /**
     * onWebSocketConnect 事件回调
     * 当客户端连接上gateway完成websocket握手时触发
     *
     * @param  integer  $client_id 断开连接的客户端client_id
     * @param  mixed    $data
     * @return void
     */
    public static function onWebSocketConnect($client_id, $data)
    {
        // token验证登录
        try{
            $Service = new GatewayService();
            if (isset($data['get']['token'])) {
                $token = $Service->tokenVerification($client_id,$data['get']['token']);
                if(!$token){
                    $Service->wsReturnError($client_id,config("config.code.not_login"),[],'连接token失效！',$Service->make['events']);
                    Gateway::closeClient($client_id);
                    Gateway::destoryClient($client_id);
                }
                $Service->wsReturnResult($client_id,[],'连接成功！',$Service->make['events']);
            }else{
                $Service->wsReturnError($client_id,[],'连接格式错误！',$Service->make['events']);
                Gateway::closeClient($client_id);
                Gateway::destoryClient($client_id);
            }
        }catch (\Exception $e){
            logWrite('Events,onWebSocketConnect', $client_id.'=>'.$e->getMessage(),__FILE__ );
            self::wsReturnError($client_id);
        }
    }

    /**
     * onMessage 事件回调
     * 当客户端发来数据(Gateway进程收到数据)后触发
     *
     * @access public
     * @param  int       $client_id
     * @param  mixed     $data
     * @return void
     */
    public static function onMessage($client_id, $data)
    {
        self::handle($client_id,$data);
    }

    /**
     * 接收参数处理
     * @param $client_id
     * @param $data
     */
    public static function handle($client_id,$data) {
        try{
            $Service = new GatewayService();
            $data = json_decode($data, true);
            $action = $data['action']; // 指定调用方法
            $params = $data['params']; // 参数
            switch ($action) {
                case 'logout':
                    $Service->logout($client_id);
                    break;
                case 'heartbeat':
                    $Service->heartbeat($client_id);
                    break;
            }
        }catch (\Exception $e){
            logWrite('Events,handle', $client_id.'=>'.$e->getMessage(),__FILE__ );
            $result = ['code'=>config("config.code.error"),'data'=>'','message'=>config("config.describe.error")];
            self::sendToClient($client_id,json_encode($result));
        }
    }

    /**
     * 异常处理返回
     * @param $client_id
     */
    public static function wsReturnError($client_id){
        $result = ['code'=>config("config.code.error"),'data'=>'','message'=>'socket服务内部错误'];
        self::sendToClient($client_id,json_encode($result));
    }

    /**
     * onClose 事件回调 当用户断开连接时触发的方法
     *
     * @param  integer $client_id 断开连接的客户端client_id
     * @return void
     */
    public static function onClose($client_id)
    {
        try{
            $Service = new GatewayService();
            $Service->logout($client_id);
//            GateWay::sendToAll("客户端=>[$client_id] 断开连接！\n");
        }catch (\Exception $e){
            logWrite('Events,onClose', $client_id.'=>'.$e->getMessage(),__FILE__ );
            self::returnError($client_id);
        }
    }

    /**
     * onWorkerStop 事件回调
     * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
     *
     * @param  \Workerman\Worker    $businessWorker
     * @return void
     */
    public static function onWorkerStop(Worker $businessWorker)
    {
        Log::write("-5");
        echo "WorkerStop\n";
    }

    /**
     * 给指定客户端发送消息
     * @param $client_id //ID
     * @param $data     // 数据
     */
    public static function sendToClient($client_id,$data){
        Gateway::sendToClient($client_id,$data);
    }

    /**
     * 广播所有客户端
     * @param $data //数据
     * @throws \Exception
     */
    public static function sendToAll($data){
        Gateway::sendToAll($data);
    }

    /**
     * 获取当前在线客户端数量
     */
    public static function getAllClientIdCount(){
        return Gateway::getAllClientIdCount();
    }

    /**
     * 获取在线的客户端$client_id信息
     * @return array
     */
    public static function getAllClientIdList(){
        return Gateway::getAllClientIdList();
    }

    /**
     * 踢掉某个客户端，并以$message通知被踢掉客户端
     * @param $client_id //id
     * @param $message // 消息
     */
    public static function closeClient($client_id, $message){
        Gateway::closeClient($client_id, $message);
    }

    /**
     * 定时器
     */
    public static function timer(){
        try {
            Timer::add(0.1, function () {
                $RedisModel = new RedisModel();
                $label_meta = $RedisModel->getValue('huisheng_ft_nlp');
                if ($label_meta == 1) {
                    if (file_exists('/opt/huisheng/huisheng_ft_nlp/codes/status')) {
                        $RedisModel->setValue('huisheng_ft_nlp', 2);
                        Events::synchronizationInstruction();
                        exec('docker restart huisheng_ft_nlp');
                    }
                }
            });
        }catch (\Exception $e){
            exception($e,'Events.timer');
        }
    }
    public static function synchronizationInstruction(){
        Db::table('label')->where('status',2)->delete();
        $url = config("config.externalServices.address");
        $query = ['id'=>1,'get_labels'=>True];
        $result =CurlHandle::jsonPost($url,$query);
        $result = json_decode($result,true);
        $bus = new LabelBus();
        if($result){
            $data = [];
            $list = Db::name('label')->where('status', 1)->field('')->select();
            foreach ($list as $key => $val){
                array_push($data,$val['label']);
            }
            $nlpData = [];
            if($result['result']){
                foreach ($result['result'] as $key => $val){
                    if(!in_array($val,$data)){
                        $arr = ['status'=>1,'label'=>$val];
                        array_push($nlpData,$arr);
                    }
                }
            }
            $bus->batchUpdate($nlpData);
        }
    }
}
